#include "tools.h"


Goods goods[GOODS_MAX];
Vip vip[VIP_MAX];
Person person[PERSON_MAX];
Money money;
Md5_value md5_value;

int cnt_goods; 
int cnt_vip;
int cnt_person;

char get_cmd(char start,char end)
{
	assert(start <= end);

	puts("-------------------");
	printf("请输入指令：");
	for(;;)
	{
		char cmd = getch();
		if(start <= cmd && cmd <= end)
		{
			printf("%c\n",cmd);
			return cmd;
		}
	}
}

void print_sec(const char* msg,float sec)
{
	printf("\33[01;32m %s \33[00m\n",msg);
	usleep(1000000*sec);
}

void anykey_continue(void)
{
	fflush(stdin);
	puts("按任意键继续...");
	getch();
}

char* get_str(char* str,size_t size)
{
	assert(NULL!=str && size>1);

	// 计算fgets读取了多少个字符
	size_t len = strlen(fgets(str,size,stdin));

	// 如果最后一个字符是'\n'，则把它改为'\0'
	if('\n' == str[len-1])
		str[len-1] = '\0';
	else
		// 如果最后一个字符不是'\n'，则说明缓冲区中有垃圾数据，则需要清理输入缓冲区
		while('\n' != getchar());
	return str;
}

char* get_passwd(char* passwd,size_t size)
{
	int i = 0;
	while(i < size-1)
	{
		passwd[i] = getch();

		// 读取到退格键
		if(127 == passwd[i])
		{
			// 数组中有已输入密码
			if(i > 0)
			{
				// 删除一位密码
				i--;
				printf("\b \b");
			}
			continue;
		}
		if('\n' == passwd[i])
		{
			break;
		}
		
		i++;
		printf("*");
	}
	passwd[i] = '\0';
	printf("\n");
	return passwd;
}

bool yes_or_no(void)
{
	printf("是否确认此操作(y/n)?");
	for(;;)
	{
		char cmd = getch();
		if('y' == cmd || 'Y' == cmd || 'n' == cmd || 'N' == cmd)
		{
			printf("%c\n",cmd);
			return 'y'==cmd || 'Y'==cmd;
		}
	}
}

// 通用的二进制保存数据
int save_data(void* base,size_t size,const char* path)
{
	assert(NULL!=base && 0!=size && NULL!=path);

	FILE* wfp = fopen(path,"w");
	if(NULL == wfp)
	{
		printf("无法打开文件，无法保存数据！\n");
		return 0;
	}

	int ret = fwrite(base,1,size,wfp);
	fclose(wfp);
	return ret;
}

// 通用的二进制加载数据
int load_data(void* base,size_t size,const char* path)
{
	assert(NULL!=base && 0!=size && NULL!=path);

	FILE* rfp = fopen(path,"r");
	if(NULL == rfp)
	{
		printf("无法打开文件，加载数据失败！\n");
		return 0;
	}

	int ret = fread(base,1,size,rfp);
	fclose(rfp);
	return ret;
}

//查找函数

int query_goodsname(const char* name)      //用商品名查找商品
{
	for(int i=0; i<cnt_goods; i++)
	{
		if(0 == strcmp(goods[i].name,name))
		{
			return i;
		}
	}
	return -1;
}


int query_goodsid(const int id)      	//用商品ID查找商品
{
	for(int i=0; i<cnt_goods; i++)
	{
		if(id == goods[i].id)
		{
			return i;
		}
	}
	return -1;
}


int query_vipphone(const char* phone) 		//用VIP电话 查找VIP
{
	for(int i=0; i<cnt_vip; i++)
	{
		if(0 == strcmp(vip[i].phone,phone))
		{
				return i;
		}
	}
	return -1;
}

int query_personid(const int id) 		//用员工ID 查找员工
{
	for(int i=0; i<cnt_person; i++)
	{
		if(id == person[i].id)
			return i;
	}
	return -1;
}


int get_personid(void)          		//自动寻找后勤空余ID
{
	for(int i=101;i<200;i++)
	{
		if(-1 == query_personid(i))
		{
			return i;
		}
	}
	return -1;
}




//删除函数
void reduce(int place,int type)      //删除三种结构体 type来区分 1.后勤人员 2.VIP 3.商品  
{
	assert(REDUCE_PERSON == type || REDUCE_VIP == type || REDUCE_GOODS == type);    
	if(REDUCE_PERSON == type)
	{
		if(yes_or_no())
		{
			// 把最后一个用户移动给要删除的用户位置
			person[place] = person[cnt_person-1];
			// 后勤人数数量减1
			cnt_person--;
			print_sec("删除后勤人员成功！",0.75);
			return;
		}
		print_sec("取消删除操作！",0.75);
	}
	else if(REDUCE_VIP == type)
	{ 
		if(yes_or_no())
		{
			// 把最后一个VIP移动给要删除的VIP位置
			vip[place] = vip[cnt_vip-1];
			// 后勤人数数量减1
			cnt_vip--;
			print_sec("删除VIP成功！",0.75);
			return;
		}
		print_sec("取消删除操作！",0.75);
	}
	else if(REDUCE_GOODS == type)
	{
		if(yes_or_no())
		{
			// 把最后一个商品移动给要删除的商品位置
			goods[place] = goods[cnt_goods-1];
			// 商品种类数量减1
			cnt_goods--;
			print_sec("删除商品成功！",0.75);
			return;
		}
		print_sec("取消删除操作！",0.75);
	}

}

int cmp_personid(const void* p1, const void* p2)			 //比较person中的id大小
{
	return ((Person*)p1)->id - ((Person*)p2)->id;            //本质是比较整形
}

int cmp_points(const void* p1, const void* p2)				//比较VIP中的points大小
{
	return (((Vip*)p2)->points - ((Vip*)p1)->points);
}

int cmp_goodsid(const void* p1, const void* p2)			 	//比较goodsn中的id大小
{
	return ((Goods*)p1)->id - ((Goods*)p2)->id;
}

void load_alldata_main(void)
{
	load_data(&md5_value,sizeof(Md5_value),"queryfile.dat");
	cnt_person = load_data(person,sizeof(person),"person.dat") / sizeof(Person);
	cnt_vip = load_data(vip,sizeof(vip),"vip.dat") / sizeof(Vip);
	cnt_goods = load_data(goods,sizeof(goods),"goods.dat") / sizeof(Goods);
	load_data(&money,sizeof(money),"money.dat");
	if(0 != cnt_person)    									//检验文件是否损坏或被更改
	{
		if(!query_file("person.dat",QUERY_PERSON))
		{
			print_sec("person.dat文件内存损坏或文件内容被人篡改,请联系管理员",3);
			exit(0);
		}
	}
	if(0 != cnt_vip)
	{
		if(!query_file("vip.dat",QUERY_VIP))
		{
			print_sec("vip.dat文件内存损坏或文件内容被人篡改,请联系管理员",3);
			exit(0);
		}
	}
	if(0 != cnt_goods)
	{
		if(!query_file("goods.dat",QUERY_GOODS))
		{
			print_sec("goods.dat文件内存损坏或文件内容被人篡改,请联系管理员",3);
			exit(0);
		}
	}
}

void save_alldata_main(void)
{
	save_data(person,sizeof(Person)*cnt_person,"person.dat");
	save_data(vip,sizeof(Vip)*cnt_vip,"vip.dat");
	save_data(&money,sizeof(money),"money.dat");
	save_data(goods,sizeof(Goods)*cnt_goods,"goods.dat");
	save_file_md5();
	save_data(&md5_value,sizeof(md5_value),"queryfile.dat");
}


void save_file_md5()  							//保存时获取文件最后的MD5值并存入文件
{
	get_file_md5("person.dat",md5_value.person_value);
	get_file_md5("vip.dat",md5_value.vip_value);
	get_file_md5("goods.dat",md5_value.goods_value);
}

void get_file_md5(const char* path,unsigned char* value)			//获取文件MD5值封装函数
{
	assert(NULL!=path);
	FILE* fp = fopen(path,"r");
	MD5_CTX md5;
	MD5Init(&md5);
	do 
	{
		unsigned char encrypt[1024];
		while(!feof(fp))
		{
			MD5Update(&md5, encrypt, fread(encrypt, 1, sizeof(encrypt), fp));
		}
		fclose(fp);
	} while(0);
	unsigned char decrypt[17];
	MD5Final(&md5, decrypt);
	decrypt[16] = '\0';
	strcpy((char*)value,(char*)decrypt);
}

bool query_file(const char* path1,int type)				//对比文件是否一致 不一致返回false
{
	assert(NULL!=path1);
	FILE* fp = fopen(path1,"r");
	MD5_CTX md5;
	MD5Init(&md5);
	do 
	{
		unsigned char encrypt[1024];
		while(!feof(fp))
		{
			MD5Update(&md5, encrypt, fread(encrypt, 1, sizeof(encrypt), fp));
		}
		fclose(fp);
	} while(0);
	unsigned char decrypt[17];
	MD5Final(&md5, decrypt);
	decrypt[16] = '\0';
	bool flag = true;
	if(QUERY_PERSON == type)
	{
		if(0 != strcmp((char*)decrypt,(char*)md5_value.person_value))
			flag = false;
	}
	else if(QUERY_VIP == type)
	{
		if(0 != strcmp((char*)decrypt,(char*)md5_value.vip_value))
			flag = false;
	}
	else if(QUERY_GOODS == type)
	{
		if(0 != strcmp((char*)decrypt,(char*)md5_value.goods_value))
			flag = false;
	}
	return flag;
}


//排序函数
/*
void sort_goods(Goods *p,int n)				//排序商品,以ID为标准
{
	assert(n >= 0 && NULL != p);
	int step = 0;//步长
    Goods temp;//用来保存第二段数据
    int i,j;
 
    for(step = n / 2;step > 0;step /= 2)
    {
        for(i = step;i < n;i++)
        {
            temp = p[i];
            for(j = i - step;j >= 0 && p[j].id > temp.id;j -= step)
            {
                p[j + step] = p[j];
                //当满足条件时第一次j+step = i;后面的j+step = 上一次j的值
            }
            p[j + step] = temp;
        }
    }
}

void sort_person(Person *p,int n)				//排序后勤人员,以ID为标准
{
	assert(n >= 0 && NULL != p);
	int step = 0;//步长
    Person temp;//用来保存第二段数据
    int i,j;
 
    for(step = n / 2;step > 0;step /= 2)
    {
        for(i = step;i < n;i++)
        {
            temp = p[i];
            for(j = i - step;j >= 0 && p[j].id > temp.id;j -= step)
            {
                p[j + step] = p[j];
                //当满足条件时第一次j+step = i;后面的j+step = 上一次j的值
            }
            p[j + step] = temp;
        }
    }
}

void sort_vip(Vip *p,int n)				//排序VIP,以积分为标准
{
	assert(n >= 0 && NULL != p);
	int step = 0;//步长
    Vip temp;//用来保存第二段数据
    int i,j;
 
    for(step = n / 2;step > 0;step /= 2)
    {
        for(i = step;i < n;i++)
        {
            temp = p[i];
            for(j = i - step;j >= 0 && p[j].points < temp.points;j -= step)
            {
                p[j + step] = p[j];
                //当满足条件时第一次j+step = i;后面的j+step = 上一次j的值
            }
            p[j + step] = temp;
        }
    }
}
*/